import typing as tp

from fastapi import FastAPI
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.openapi.utils import get_openapi
from fastapi.responses import RedirectResponse, JSONResponse
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.responses import HTMLResponse
from starlette.staticfiles import StaticFiles

from .configs import app as APP
from .exception_handlers import register_exception_handlers
from .resources import register_resources
from .responses._all import MyGlobalResponse


def my_openapi(app):
    def f():
        if app.openapi_schema:
            return app.openapi_schema
        # Info
        contact = {
            "name": 'aponder',
            "url": 'http://aponder.top',
            "email": 'it@aponder.top',
        }
        openapi_schema = get_openapi(
            title=APP.PROJECT_NAME,
            version='0.0.1',
            # openapi_version="2.5.0",
            description='1112222333',
            routes=app.routes,
            tags=None,
            servers=None,
            terms_of_service="不知道的ToS",
            contact=contact,
            license_info={
                "name": '未授权',
                "url": 'http://aponder.top',
            }
        )
        openapi_schema["info"]["x-logo"] = {
            "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png"
        }
        app.openapi_schema = openapi_schema
        return app.openapi_schema

    return f


def create_app(app_env='production') -> FastAPI:
    app = FastAPI(
        title=APP.PROJECT_NAME,
        description='',
        version='0.1.0',
        # openapi_url='/static/server1.json',
        default_response_class=MyGlobalResponse,
        # docs_url="/",
        # redoc_url="/",
        # root_path='/api',
    )

    # app.openapi = my_openapi(app)

    # Set all CORS enabled origins
    app.add_middleware(
        CORSMiddleware,
        allow_origins=APP.ALLOW_ORIGINS,
        allow_credentials=APP.ALLOW_CREDENTIALS,
        allow_methods=APP.ALLOW_METHODS,
        allow_headers=APP.ALLOW_HEADERS,
    )

    # register all resources
    register_resources(app)

    # register_api_doc(app)
    register_swagger_doc(app)
    register_exception_handlers(app)

    return app


def register_api_doc(app: FastAPI):
    @app.get("/", include_in_schema=False)
    async def redirect_typer():
        return RedirectResponse("/index.html")

    from fastapi.staticfiles import StaticFiles
    app.mount('/', StaticFiles(directory=str(APP.PROJECT_PATH / 'api_doc')), name='api_doc')


def register_swagger_doc(app: FastAPI):
    app.mount('/static', StaticFiles(directory=str(APP.PROJECT_PATH / 'static')), name='static')

    async def swagger_ui_html(req: Request) -> HTMLResponse:
        root_path = req.scope.get("root_path", "").rstrip("/")
        openapi_url = root_path + app.openapi_url
        oauth2_redirect_url = app.swagger_ui_oauth2_redirect_url
        if oauth2_redirect_url:
            oauth2_redirect_url = root_path + oauth2_redirect_url
        return get_swagger_ui_html(
            openapi_url=openapi_url,
            title=app.title + " - Swagger UI",
            oauth2_redirect_url=oauth2_redirect_url,
            init_oauth=app.swagger_ui_init_oauth,
            swagger_js_url='/static/swagger/js/swagger-ui-bundle.js',
            swagger_css_url='/static/swagger/css/swagger-ui.css',
        )

    print(app.docs_url)

    app.add_route('/', swagger_ui_html, include_in_schema=False)
